net: qede: stop adding events on an already destroyed workqueue
[linux-2.6-microblaze.git] / mm / page_alloc.c
index 7277512..48eb0f1 100644 (file)
@@ -8285,6 +8285,19 @@ struct page *has_unmovable_pages(struct zone *zone, struct page *page,
                if ((flags & MEMORY_OFFLINE) && PageHWPoison(page))
                        continue;
 
+               /*
+                * We treat all PageOffline() pages as movable when offlining
+                * to give drivers a chance to decrement their reference count
+                * in MEM_GOING_OFFLINE in order to indicate that these pages
+                * can be offlined as there are no direct references anymore.
+                * For actually unmovable PageOffline() where the driver does
+                * not support this, we will fail later when trying to actually
+                * move these pages that still have a reference count > 0.
+                * (false negatives in this function only)
+                */
+               if ((flags & MEMORY_OFFLINE) && PageOffline(page))
+                       continue;
+
                if (__PageMovable(page) || PageLRU(page))
                        continue;
 
@@ -8516,6 +8529,7 @@ done:
                                pfn_max_align_up(end), migratetype);
        return ret;
 }
+EXPORT_SYMBOL(alloc_contig_range);
 
 static int __alloc_contig_pages(unsigned long start_pfn,
                                unsigned long nr_pages, gfp_t gfp_mask)
@@ -8631,6 +8645,7 @@ void free_contig_range(unsigned long pfn, unsigned int nr_pages)
        }
        WARN(count != 0, "%d pages are still in use!\n", count);
 }
+EXPORT_SYMBOL(free_contig_range);
 
 /*
  * The zone indicated has a new number of managed_pages; batch sizes and percpu
@@ -8703,6 +8718,17 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
                        offlined_pages++;
                        continue;
                }
+               /*
+                * At this point all remaining PageOffline() pages have a
+                * reference count of 0 and can simply be skipped.
+                */
+               if (PageOffline(page)) {
+                       BUG_ON(page_count(page));
+                       BUG_ON(PageBuddy(page));
+                       pfn++;
+                       offlined_pages++;
+                       continue;
+               }
 
                BUG_ON(page_count(page));
                BUG_ON(!PageBuddy(page));