]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - include/linux/mm.h
mm: Make generic weak get_user_pages_fast and EXPORT_GPL it
[linux-2.6.git] / include / linux / mm.h
index 3b3e1341163f3075321b487362dc8bba0bab91f3..fa651609b65dbc928a1a3d20035c29b42a1a8947 100644 (file)
@@ -41,6 +41,9 @@ extern unsigned long mmap_min_addr;
 
 #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
 
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
+
 /*
  * Linux kernel virtual memory manager primitives.
  * The idea being to have a "virtual" mm in the same way
@@ -100,6 +103,7 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_DONTEXPAND  0x00040000      /* Cannot expand with mremap() */
 #define VM_RESERVED    0x00080000      /* Count as reserved_vm like IO */
 #define VM_ACCOUNT     0x00100000      /* Is a VM accounted object */
+#define VM_NORESERVE   0x00200000      /* should the VM suppress accounting */
 #define VM_HUGETLB     0x00400000      /* Huge TLB Page VM */
 #define VM_NONLINEAR   0x00800000      /* Is non-linear (remap_file_pages) */
 #define VM_MAPPED_COPY 0x01000000      /* T if mapped copy of data (nommu mmap) */
@@ -107,6 +111,8 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_ALWAYSDUMP  0x04000000      /* Always include in core dumps */
 
 #define VM_CAN_NONLINEAR 0x08000000    /* Has ->fault & does nonlinear pages */
+#define VM_MIXEDMAP    0x10000000      /* Can contain "struct page" and pure PFN pages */
+#define VM_SAO         0x20000000      /* Strong Access Ordering (powerpc) */
 
 #ifndef VM_STACK_DEFAULT_FLAGS         /* arch can override this */
 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
@@ -164,16 +170,36 @@ struct vm_operations_struct {
        void (*open)(struct vm_area_struct * area);
        void (*close)(struct vm_area_struct * area);
        int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
-       struct page *(*nopage)(struct vm_area_struct *area,
-                       unsigned long address, int *type);
-       unsigned long (*nopfn)(struct vm_area_struct *area,
-                       unsigned long address);
 
        /* notification that a previously read-only page is about to become
         * writable, if an error is returned it will cause a SIGBUS */
        int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page);
+
+       /* called by access_process_vm when get_user_pages() fails, typically
+        * for use by special VMAs that can switch between memory and hardware
+        */
+       int (*access)(struct vm_area_struct *vma, unsigned long addr,
+                     void *buf, int len, int write);
 #ifdef CONFIG_NUMA
+       /*
+        * set_policy() op must add a reference to any non-NULL @new mempolicy
+        * to hold the policy upon return.  Caller should pass NULL @new to
+        * remove a policy and fall back to surrounding context--i.e. do not
+        * install a MPOL_DEFAULT policy, nor the task or system default
+        * mempolicy.
+        */
        int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
+
+       /*
+        * get_policy() op must add reference [mpol_get()] to any policy at
+        * (vma,addr) marked as MPOL_SHARED.  The shared policy infrastructure
+        * in mm/mempolicy.c will do this automatically.
+        * get_policy() must NOT add a ref if the policy at (vma,addr) is not
+        * marked as MPOL_SHARED. vma policies are protected by the mmap_sem.
+        * If no [shared/vma] mempolicy exists at the addr, get_policy() op
+        * must return NULL--i.e., do not "fallback" to task or system default
+        * policy.
+        */
        struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
                                        unsigned long addr);
        int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from,
@@ -235,12 +261,21 @@ static inline int get_page_unless_zero(struct page *page)
 struct page *vmalloc_to_page(const void *addr);
 unsigned long vmalloc_to_pfn(const void *addr);
 
-/* Determine if an address is within the vmalloc range */
+/*
+ * Determine if an address is within the vmalloc range
+ *
+ * On nommu, vmalloc/vfree wrap through kmalloc/kfree directly, so there
+ * is no special casing required.
+ */
 static inline int is_vmalloc_addr(const void *x)
 {
+#ifdef CONFIG_MMU
        unsigned long addr = (unsigned long)x;
 
        return addr >= VMALLOC_START && addr < VMALLOC_END;
+#else
+       return 0;
+#endif
 }
 
 static inline struct page *compound_head(struct page *page)
@@ -388,11 +423,11 @@ static inline void set_compound_order(struct page *page, unsigned long order)
  * we have run out of space and have to fall back to an
  * alternate (slower) way of determining the node.
  *
- *        No sparsemem: |       NODE     | ZONE | ... | FLAGS |
- * with space for node: | SECTION | NODE | ZONE | ... | FLAGS |
- *   no space for node: | SECTION |     ZONE    | ... | FLAGS |
+ * No sparsemem or sparsemem vmemmap: |       NODE     | ZONE | ... | FLAGS |
+ * classic sparse with space for node:| SECTION | NODE | ZONE | ... | FLAGS |
+ * classic sparse no space for node:  | SECTION |     ZONE    | ... | FLAGS |
  */
-#ifdef CONFIG_SPARSEMEM
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
 #define SECTIONS_WIDTH         SECTIONS_SHIFT
 #else
 #define SECTIONS_WIDTH         0
@@ -400,9 +435,12 @@ static inline void set_compound_order(struct page *page, unsigned long order)
 
 #define ZONES_WIDTH            ZONES_SHIFT
 
-#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= FLAGS_RESERVED
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= BITS_PER_LONG - NR_PAGEFLAGS
 #define NODES_WIDTH            NODES_SHIFT
 #else
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+#error "Vmemmap: No space for nodes field in page flags"
+#endif
 #define NODES_WIDTH            0
 #endif
 
@@ -445,8 +483,8 @@ static inline void set_compound_order(struct page *page, unsigned long order)
 
 #define ZONEID_PGSHIFT         (ZONEID_PGOFF * (ZONEID_SHIFT != 0))
 
-#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
-#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
+#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > BITS_PER_LONG - NR_PAGEFLAGS
 #endif
 
 #define ZONES_MASK             ((1UL << ZONES_WIDTH) - 1)
@@ -495,10 +533,12 @@ static inline struct zone *page_zone(struct page *page)
        return &NODE_DATA(page_to_nid(page))->node_zones[page_zonenum(page)];
 }
 
+#if defined(CONFIG_SPARSEMEM) && !defined(CONFIG_SPARSEMEM_VMEMMAP)
 static inline unsigned long page_to_section(struct page *page)
 {
        return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
 }
+#endif
 
 static inline void set_page_zone(struct page *page, enum zone_type zone)
 {
@@ -593,9 +633,12 @@ static inline struct address_space *page_mapping(struct page *page)
        struct address_space *mapping = page->mapping;
 
        VM_BUG_ON(PageSlab(page));
+#ifdef CONFIG_SWAP
        if (unlikely(PageSwapCache(page)))
                mapping = &swapper_space;
-       else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
+       else
+#endif
+       if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON))
                mapping = NULL;
        return mapping;
 }
@@ -639,19 +682,6 @@ static inline int page_mapped(struct page *page)
        return atomic_read(&(page)->_mapcount) >= 0;
 }
 
-/*
- * Error return values for the *_nopage functions
- */
-#define NOPAGE_SIGBUS  (NULL)
-#define NOPAGE_OOM     ((struct page *) (-1))
-
-/*
- * Error return values for the *_nopfn functions
- */
-#define NOPFN_SIGBUS   ((unsigned long) -1)
-#define NOPFN_OOM      ((unsigned long) -2)
-#define NOPFN_REFAULT  ((unsigned long) -3)
-
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
  * Used to decide whether a process gets delivered SIGBUS or
@@ -711,7 +741,11 @@ struct zap_details {
        unsigned long truncate_count;           /* Compare vm_truncate_count */
 };
 
-struct page *vm_normal_page(struct vm_area_struct *, unsigned long, pte_t);
+struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
+               pte_t pte);
+
+int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
+               unsigned long size);
 unsigned long zap_page_range(struct vm_area_struct *vma, unsigned long address,
                unsigned long size, struct zap_details *);
 unsigned long unmap_vmas(struct mmu_gather **tlb,
@@ -730,24 +764,25 @@ unsigned long unmap_vmas(struct mmu_gather **tlb,
  * (see walk_page_range for more details)
  */
 struct mm_walk {
-       int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *);
-       int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *);
-       int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *);
-       int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *);
-       int (*pte_hole)(unsigned long, unsigned long, void *);
+       int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, struct mm_walk *);
+       int (*pud_entry)(pud_t *, unsigned long, unsigned long, struct mm_walk *);
+       int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, struct mm_walk *);
+       int (*pte_entry)(pte_t *, unsigned long, unsigned long, struct mm_walk *);
+       int (*pte_hole)(unsigned long, unsigned long, struct mm_walk *);
+       struct mm_struct *mm;
+       void *private;
 };
 
-int walk_page_range(const struct mm_struct *, unsigned long addr,
-                   unsigned long end, const struct mm_walk *walk,
-                   void *private);
-void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+int walk_page_range(unsigned long addr, unsigned long end,
+               struct mm_walk *walk);
+void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
                unsigned long end, unsigned long floor, unsigned long ceiling);
-void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
-               unsigned long floor, unsigned long ceiling);
 int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
                        struct vm_area_struct *vma);
 void unmap_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen, int even_cows);
+int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
+                       void *buf, int len, int write);
 
 static inline void unmap_shared_mapping_range(struct address_space *mapping,
                loff_t const holebegin, loff_t const holelen)
@@ -777,7 +812,6 @@ extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *
 
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
                int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
-void print_bad_pte(struct vm_area_struct *, pte_t, unsigned long);
 
 extern int try_to_release_page(struct page * page, gfp_t gfp_mask);
 extern void do_invalidatepage(struct page *page, unsigned long offset);
@@ -800,6 +834,19 @@ extern int mprotect_fixup(struct vm_area_struct *vma,
                          struct vm_area_struct **pprev, unsigned long start,
                          unsigned long end, unsigned long newflags);
 
+/*
+ * get_user_pages_fast provides equivalent functionality to get_user_pages,
+ * operating on current and current->mm (force=0 and doesn't return any vmas).
+ *
+ * get_user_pages_fast may take mmap_sem and page tables, so no assumptions
+ * can be made about locking. get_user_pages_fast is to be implemented in a
+ * way that is advantageous (vs get_user_pages()) when the user memory area is
+ * already faulted in and present in ptes. However if the pages have to be
+ * faulted in, it may turn out to be slightly slower).
+ */
+int get_user_pages_fast(unsigned long start, int nr_pages, int write,
+                       struct page **pages);
+
 /*
  * A callback you can register to apply pressure to ageable caches.
  *
@@ -933,9 +980,8 @@ static inline void pgtable_page_dtor(struct page *page)
                NULL: pte_offset_kernel(pmd, address))
 
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat,
-       unsigned long * zones_size, unsigned long zone_start_pfn, 
-       unsigned long *zholes_size);
+extern void free_area_init_node(int nid, unsigned long * zones_size,
+               unsigned long zone_start_pfn, unsigned long *zholes_size);
 #ifdef CONFIG_ARCH_POPULATES_NODE_MAP
 /*
  * With CONFIG_ARCH_POPULATES_NODE_MAP set, an architecture may initialise its
@@ -967,8 +1013,8 @@ extern void free_area_init_node(int nid, pg_data_t *pgdat,
 extern void free_area_init_nodes(unsigned long *max_zone_pfn);
 extern void add_active_range(unsigned int nid, unsigned long start_pfn,
                                        unsigned long end_pfn);
-extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
-                                               unsigned long new_end_pfn);
+extern void remove_active_range(unsigned int nid, unsigned long start_pfn,
+                                       unsigned long end_pfn);
 extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn,
                                        unsigned long end_pfn);
 extern void remove_all_active_ranges(void);
@@ -977,9 +1023,10 @@ extern unsigned long absent_pages_in_range(unsigned long start_pfn,
 extern void get_pfn_range_for_nid(unsigned int nid,
                        unsigned long *start_pfn, unsigned long *end_pfn);
 extern unsigned long find_min_pfn_with_active_regions(void);
-extern unsigned long find_max_pfn_with_active_regions(void);
 extern void free_bootmem_with_active_regions(int nid,
                                                unsigned long max_low_pfn);
+typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
+extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
 extern void sparse_memory_present_with_active_regions(int nid);
 #ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
 extern int early_pfn_to_nid(unsigned long pfn);
@@ -993,6 +1040,7 @@ extern void mem_init(void);
 extern void show_mem(void);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
+extern int after_bootmem;
 
 #ifdef CONFIG_NUMA
 extern void setup_per_cpu_pageset(void);
@@ -1036,6 +1084,22 @@ extern void unlink_file_vma(struct vm_area_struct *);
 extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
        unsigned long addr, unsigned long len, pgoff_t pgoff);
 extern void exit_mmap(struct mm_struct *);
+
+extern int mm_take_all_locks(struct mm_struct *mm);
+extern void mm_drop_all_locks(struct mm_struct *mm);
+
+#ifdef CONFIG_PROC_FS
+/* From fs/proc/base.c. callers must _not_ hold the mm's exe_file_lock */
+extern void added_exe_file_vma(struct mm_struct *mm);
+extern void removed_exe_file_vma(struct mm_struct *mm);
+#else
+static inline void added_exe_file_vma(struct mm_struct *mm)
+{}
+
+static inline void removed_exe_file_vma(struct mm_struct *mm)
+{}
+#endif /* CONFIG_PROC_FS */
+
 extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 extern int install_special_mapping(struct mm_struct *mm,
                                   unsigned long addr, unsigned long len,
@@ -1140,6 +1204,8 @@ int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
 int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
 int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
                        unsigned long pfn);
+int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
+                       unsigned long pfn);
 
 struct page *follow_page(struct vm_area_struct *, unsigned long address,
                        unsigned int foll_flags);
@@ -1198,8 +1264,6 @@ int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *,
                                        void __user *, size_t *, loff_t *);
 unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
                        unsigned long lru_pages);
-void drop_pagecache(void);
-void drop_slab(void);
 
 #ifndef CONFIG_MMU
 #define randomize_va_space 0
@@ -1220,6 +1284,7 @@ void vmemmap_verify(pte_t *, int, unsigned long, unsigned long);
 int vmemmap_populate_basepages(struct page *start_page,
                                                unsigned long pages, int node);
 int vmemmap_populate(struct page *start_page, unsigned long pages, int node);
+void vmemmap_populate_print_last(void);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */