ARM: tegra: add sysfs support for tegra cpuquiet driver
[linux-2.6.git] / include / linux / pagemap.h
index a39b38c..cfaaa69 100644 (file)
 #include <linux/gfp.h>
 #include <linux/bitops.h>
 #include <linux/hardirq.h> /* for in_interrupt() */
+#include <linux/hugetlb_inline.h>
 
 /*
  * Bits in mapping->flags.  The lower __GFP_BITS_SHIFT bits are the page
  * allocation mode flags.
  */
-#define        AS_EIO          (__GFP_BITS_SHIFT + 0)  /* IO error on async write */
-#define AS_ENOSPC      (__GFP_BITS_SHIFT + 1)  /* ENOSPC on async write */
-#define AS_MM_ALL_LOCKS        (__GFP_BITS_SHIFT + 2)  /* under mm_take_all_locks() */
+enum mapping_flags {
+       AS_EIO          = __GFP_BITS_SHIFT + 0, /* IO error on async write */
+       AS_ENOSPC       = __GFP_BITS_SHIFT + 1, /* ENOSPC on async write */
+       AS_MM_ALL_LOCKS = __GFP_BITS_SHIFT + 2, /* under mm_take_all_locks() */
+       AS_UNEVICTABLE  = __GFP_BITS_SHIFT + 3, /* e.g., ramdisk, SHM_LOCK */
+};
 
 static inline void mapping_set_error(struct address_space *mapping, int error)
 {
@@ -32,6 +36,23 @@ static inline void mapping_set_error(struct address_space *mapping, int error)
        }
 }
 
+static inline void mapping_set_unevictable(struct address_space *mapping)
+{
+       set_bit(AS_UNEVICTABLE, &mapping->flags);
+}
+
+static inline void mapping_clear_unevictable(struct address_space *mapping)
+{
+       clear_bit(AS_UNEVICTABLE, &mapping->flags);
+}
+
+static inline int mapping_unevictable(struct address_space *mapping)
+{
+       if (mapping)
+               return test_bit(AS_UNEVICTABLE, &mapping->flags);
+       return !!mapping;
+}
+
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
        return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
@@ -112,8 +133,8 @@ static inline int page_cache_get_speculative(struct page *page)
 {
        VM_BUG_ON(in_interrupt());
 
-#if !defined(CONFIG_SMP) && defined(CONFIG_CLASSIC_RCU)
-# ifdef CONFIG_PREEMPT
+#if !defined(CONFIG_SMP) && defined(CONFIG_TREE_RCU)
+# ifdef CONFIG_PREEMPT_COUNT
        VM_BUG_ON(!in_atomic());
 # endif
        /*
@@ -143,6 +164,29 @@ static inline int page_cache_get_speculative(struct page *page)
        return 1;
 }
 
+/*
+ * Same as above, but add instead of inc (could just be merged)
+ */
+static inline int page_cache_add_speculative(struct page *page, int count)
+{
+       VM_BUG_ON(in_interrupt());
+
+#if !defined(CONFIG_SMP) && defined(CONFIG_TREE_RCU)
+# ifdef CONFIG_PREEMPT_COUNT
+       VM_BUG_ON(!in_atomic());
+# endif
+       VM_BUG_ON(page_count(page) == 0);
+       atomic_add(count, &page->_count);
+
+#else
+       if (unlikely(!atomic_add_unless(&page->_count, count, 0)))
+               return 0;
+#endif
+       VM_BUG_ON(PageCompound(page) && page != compound_head(page));
+
+       return 1;
+}
+
 static inline int page_freeze_refs(struct page *page, int count)
 {
        return likely(atomic_cmpxchg(&page->_count, count, 0) == count);
@@ -175,6 +219,12 @@ static inline struct page *page_cache_alloc_cold(struct address_space *x)
        return __page_cache_alloc(mapping_gfp_mask(x)|__GFP_COLD);
 }
 
+static inline struct page *page_cache_alloc_readahead(struct address_space *x)
+{
+       return __page_cache_alloc(mapping_gfp_mask(x) |
+                                 __GFP_COLD | __GFP_NORETRY | __GFP_NOWARN);
+}
+
 typedef int filler_t(void *, struct page *);
 
 extern struct page * find_get_page(struct address_space *mapping,
@@ -190,7 +240,8 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start,
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
                        int tag, unsigned int nr_pages, struct page **pages);
 
-struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index);
+struct page *grab_cache_page_write_begin(struct address_space *mapping,
+                       pgoff_t index, unsigned flags);
 
 /*
  * Returns locked page at given index in given cache, creating it if needed.
@@ -204,52 +255,29 @@ static inline struct page *grab_cache_page(struct address_space *mapping,
 extern struct page * grab_cache_page_nowait(struct address_space *mapping,
                                pgoff_t index);
 extern struct page * read_cache_page_async(struct address_space *mapping,
-                               pgoff_t index, filler_t *filler,
-                               void *data);
+                               pgoff_t index, filler_t *filler, void *data);
 extern struct page * read_cache_page(struct address_space *mapping,
-                               pgoff_t index, filler_t *filler,
-                               void *data);
+                               pgoff_t index, filler_t *filler, void *data);
+extern struct page * read_cache_page_gfp(struct address_space *mapping,
+                               pgoff_t index, gfp_t gfp_mask);
 extern int read_cache_pages(struct address_space *mapping,
                struct list_head *pages, filler_t *filler, void *data);
 
 static inline struct page *read_mapping_page_async(
-                                               struct address_space *mapping,
-                                                    pgoff_t index, void *data)
+                               struct address_space *mapping,
+                               pgoff_t index, void *data)
 {
        filler_t *filler = (filler_t *)mapping->a_ops->readpage;
        return read_cache_page_async(mapping, index, filler, data);
 }
 
 static inline struct page *read_mapping_page(struct address_space *mapping,
-                                            pgoff_t index, void *data)
+                               pgoff_t index, void *data)
 {
        filler_t *filler = (filler_t *)mapping->a_ops->readpage;
        return read_cache_page(mapping, index, filler, data);
 }
 
-int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
-                               pgoff_t index, gfp_t gfp_mask);
-int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
-                               pgoff_t index, gfp_t gfp_mask);
-extern void remove_from_page_cache(struct page *page);
-extern void __remove_from_page_cache(struct page *page);
-
-/*
- * Like add_to_page_cache_locked, but used to add newly allocated pages:
- * the page is new, so we can just run SetPageLocked() against it.
- */
-static inline int add_to_page_cache(struct page *page,
-               struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
-{
-       int error;
-
-       SetPageLocked(page);
-       error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
-       if (unlikely(error))
-               ClearPageLocked(page);
-       return error;
-}
-
 /*
  * Return byte-offset into filesystem object for page.
  */
@@ -258,26 +286,48 @@ static inline loff_t page_offset(struct page *page)
        return ((loff_t)page->index) << PAGE_CACHE_SHIFT;
 }
 
+extern pgoff_t linear_hugepage_index(struct vm_area_struct *vma,
+                                    unsigned long address);
+
 static inline pgoff_t linear_page_index(struct vm_area_struct *vma,
                                        unsigned long address)
 {
-       pgoff_t pgoff = (address - vma->vm_start) >> PAGE_SHIFT;
+       pgoff_t pgoff;
+       if (unlikely(is_vm_hugetlb_page(vma)))
+               return linear_hugepage_index(vma, address);
+       pgoff = (address - vma->vm_start) >> PAGE_SHIFT;
        pgoff += vma->vm_pgoff;
        return pgoff >> (PAGE_CACHE_SHIFT - PAGE_SHIFT);
 }
 
 extern void __lock_page(struct page *page);
 extern int __lock_page_killable(struct page *page);
-extern void __lock_page_nosync(struct page *page);
+extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
+                               unsigned int flags);
 extern void unlock_page(struct page *page);
 
+static inline void __set_page_locked(struct page *page)
+{
+       __set_bit(PG_locked, &page->flags);
+}
+
+static inline void __clear_page_locked(struct page *page)
+{
+       __clear_bit(PG_locked, &page->flags);
+}
+
+static inline int trylock_page(struct page *page)
+{
+       return (likely(!test_and_set_bit_lock(PG_locked, &page->flags)));
+}
+
 /*
  * lock_page may only be called if we have the page's inode pinned.
  */
 static inline void lock_page(struct page *page)
 {
        might_sleep();
-       if (TestSetPageLocked(page))
+       if (!trylock_page(page))
                __lock_page(page);
 }
 
@@ -289,28 +339,37 @@ static inline void lock_page(struct page *page)
 static inline int lock_page_killable(struct page *page)
 {
        might_sleep();
-       if (TestSetPageLocked(page))
+       if (!trylock_page(page))
                return __lock_page_killable(page);
        return 0;
 }
 
 /*
- * lock_page_nosync should only be used if we can't pin the page's inode.
- * Doesn't play quite so well with block device plugging.
+ * lock_page_or_retry - Lock the page, unless this would block and the
+ * caller indicated that it can handle a retry.
  */
-static inline void lock_page_nosync(struct page *page)
+static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm,
+                                    unsigned int flags)
 {
        might_sleep();
-       if (TestSetPageLocked(page))
-               __lock_page_nosync(page);
+       return trylock_page(page) || __lock_page_or_retry(page, mm, flags);
 }
-       
+
 /*
  * This is exported only for wait_on_page_locked/wait_on_page_writeback.
  * Never use this directly!
  */
 extern void wait_on_page_bit(struct page *page, int bit_nr);
 
+extern int wait_on_page_bit_killable(struct page *page, int bit_nr);
+
+static inline int wait_on_page_locked_killable(struct page *page)
+{
+       if (PageLocked(page))
+               return wait_on_page_bit_killable(page, PG_locked);
+       return 0;
+}
+
 /* 
  * Wait for a page to be unlocked.
  *
@@ -336,6 +395,11 @@ static inline void wait_on_page_writeback(struct page *page)
 extern void end_page_writeback(struct page *page);
 
 /*
+ * Add an arbitrary waiter to a page's wait queue
+ */
+extern void add_page_wait_queue(struct page *page, wait_queue_t *waiter);
+
+/*
  * Fault a userspace page into pagetables.  Return non-zero on a fault.
  *
  * This assumes that two userspace pages are always sufficient.  That's
@@ -380,10 +444,36 @@ static inline int fault_in_pages_readable(const char __user *uaddr, int size)
                const char __user *end = uaddr + size - 1;
 
                if (((unsigned long)uaddr & PAGE_MASK) !=
-                               ((unsigned long)end & PAGE_MASK))
+                               ((unsigned long)end & PAGE_MASK)) {
                        ret = __get_user(c, end);
+                       (void)c;
+               }
        }
        return ret;
 }
 
+int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
+                               pgoff_t index, gfp_t gfp_mask);
+int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
+                               pgoff_t index, gfp_t gfp_mask);
+extern void delete_from_page_cache(struct page *page);
+extern void __delete_from_page_cache(struct page *page);
+int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask);
+
+/*
+ * Like add_to_page_cache_locked, but used to add newly allocated pages:
+ * the page is new, so we can just run __set_page_locked() against it.
+ */
+static inline int add_to_page_cache(struct page *page,
+               struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
+{
+       int error;
+
+       __set_page_locked(page);
+       error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
+       if (unlikely(error))
+               __clear_page_locked(page);
+       return error;
+}
+
 #endif /* _LINUX_PAGEMAP_H */