mm: support THPs in zero_user_segments
[linux-2.6-microblaze.git] / mm / highmem.c
index 1352a27..0ee87a9 100644 (file)
@@ -369,6 +369,58 @@ void kunmap_high(struct page *page)
 }
 
 EXPORT_SYMBOL(kunmap_high);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+void zero_user_segments(struct page *page, unsigned start1, unsigned end1,
+               unsigned start2, unsigned end2)
+{
+       unsigned int i;
+
+       BUG_ON(end1 > page_size(page) || end2 > page_size(page));
+
+       for (i = 0; i < compound_nr(page); i++) {
+               void *kaddr = NULL;
+
+               if (start1 < PAGE_SIZE || start2 < PAGE_SIZE)
+                       kaddr = kmap_atomic(page + i);
+
+               if (start1 >= PAGE_SIZE) {
+                       start1 -= PAGE_SIZE;
+                       end1 -= PAGE_SIZE;
+               } else {
+                       unsigned this_end = min_t(unsigned, end1, PAGE_SIZE);
+
+                       if (end1 > start1)
+                               memset(kaddr + start1, 0, this_end - start1);
+                       end1 -= this_end;
+                       start1 = 0;
+               }
+
+               if (start2 >= PAGE_SIZE) {
+                       start2 -= PAGE_SIZE;
+                       end2 -= PAGE_SIZE;
+               } else {
+                       unsigned this_end = min_t(unsigned, end2, PAGE_SIZE);
+
+                       if (end2 > start2)
+                               memset(kaddr + start2, 0, this_end - start2);
+                       end2 -= this_end;
+                       start2 = 0;
+               }
+
+               if (kaddr) {
+                       kunmap_atomic(kaddr);
+                       flush_dcache_page(page + i);
+               }
+
+               if (!end1 && !end2)
+                       break;
+       }
+
+       BUG_ON((start1 | start2 | end1 | end2) != 0);
+}
+EXPORT_SYMBOL(zero_user_segments);
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 #endif /* CONFIG_HIGHMEM */
 
 #if defined(HASHED_PAGE_VIRTUAL)