bfs: fix Lockdep warning
[pandora-kernel.git] / mm / util.c
index 8f18683..cb00b74 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -1,7 +1,9 @@
+#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <asm/uaccess.h>
 
 /**
@@ -68,25 +70,22 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp)
 EXPORT_SYMBOL(kmemdup);
 
 /**
- * krealloc - reallocate memory. The contents will remain unchanged.
+ * __krealloc - like krealloc() but don't free @p.
  * @p: object to reallocate memory for.
  * @new_size: how many bytes of memory are required.
  * @flags: the type of memory to allocate.
  *
- * The contents of the object pointed to are preserved up to the
- * lesser of the new and old sizes.  If @p is %NULL, krealloc()
- * behaves exactly like kmalloc().  If @size is 0 and @p is not a
- * %NULL pointer, the object pointed to is freed.
+ * This function is like krealloc() except it never frees the originally
+ * allocated buffer. Use this if you don't want to free the buffer immediately
+ * like, for example, with RCU.
  */
-void *krealloc(const void *p, size_t new_size, gfp_t flags)
+void *__krealloc(const void *p, size_t new_size, gfp_t flags)
 {
        void *ret;
        size_t ks = 0;
 
-       if (unlikely(!new_size)) {
-               kfree(p);
+       if (unlikely(!new_size))
                return ZERO_SIZE_PTR;
-       }
 
        if (p)
                ks = ksize(p);
@@ -95,10 +94,37 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
                return (void *)p;
 
        ret = kmalloc_track_caller(new_size, flags);
-       if (ret && p) {
+       if (ret && p)
                memcpy(ret, p, ks);
+
+       return ret;
+}
+EXPORT_SYMBOL(__krealloc);
+
+/**
+ * krealloc - reallocate memory. The contents will remain unchanged.
+ * @p: object to reallocate memory for.
+ * @new_size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * The contents of the object pointed to are preserved up to the
+ * lesser of the new and old sizes.  If @p is %NULL, krealloc()
+ * behaves exactly like kmalloc().  If @size is 0 and @p is not a
+ * %NULL pointer, the object pointed to is freed.
+ */
+void *krealloc(const void *p, size_t new_size, gfp_t flags)
+{
+       void *ret;
+
+       if (unlikely(!new_size)) {
                kfree(p);
+               return ZERO_SIZE_PTR;
        }
+
+       ret = __krealloc(p, new_size, flags);
+       if (ret && p != ret)
+               kfree(p);
+
        return ret;
 }
 EXPORT_SYMBOL(krealloc);
@@ -136,3 +162,27 @@ char *strndup_user(const char __user *s, long n)
        return p;
 }
 EXPORT_SYMBOL(strndup_user);
+
+#ifndef HAVE_ARCH_PICK_MMAP_LAYOUT
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+       mm->mmap_base = TASK_UNMAPPED_BASE;
+       mm->get_unmapped_area = arch_get_unmapped_area;
+       mm->unmap_area = arch_unmap_area;
+}
+#endif
+
+int __attribute__((weak)) get_user_pages_fast(unsigned long start,
+                               int nr_pages, int write, struct page **pages)
+{
+       struct mm_struct *mm = current->mm;
+       int ret;
+
+       down_read(&mm->mmap_sem);
+       ret = get_user_pages(current, mm, start, nr_pages,
+                                       write, 0, pages, NULL);
+       up_read(&mm->mmap_sem);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(get_user_pages_fast);