/* loop through free list adding unreported pages to sg list */
list_for_each_entry_safe(page, next, list, lru) { /* We are going to skip over the reported pages. */ if (PageReported(page)) continue;
/* *Ifwefullyconsumedourbudgetthenupdateour *statetoindicatethatwearerequestingadditional *processingandexitthislist.
*/ if (budget < 0) {
atomic_set(&prdev->state, PAGE_REPORTING_REQUESTED);
next = page; break;
}
/* Attempt to pull page from list and place in scatterlist */ if (*offset) { if (!__isolate_free_page(page, order)) {
next = page; break;
}
/* Add page to scatter list */
--(*offset);
sg_set_page(&sgl[*offset], page, page_len, 0);
continue;
}
/* *Makethefirstnon-reportedpageinthefreelist *thenewheadofthefreelistbeforewereleasethe *zonelock.
*/ if (!list_is_first(&page->lru, list))
list_rotate_to_front(&page->lru, list);
/* release lock before waiting on report processing */
spin_unlock_irq(&zone->lock);
/* begin processing pages in local list */
err = prdev->report(prdev, sgl, PAGE_REPORTING_CAPACITY);
/* reset offset since the full list was reported */
*offset = PAGE_REPORTING_CAPACITY;
/* update budget to reflect call to report function */
budget--;
/* reacquire zone lock and resume processing */
spin_lock_irq(&zone->lock);
/* flush reported pages from the sg list */
page_reporting_drain(prdev, sgl, PAGE_REPORTING_CAPACITY, !err);
/* *Resetnexttofirstentry,theoldnextisn'tvalid *sincewedroppedthelocktoreportthepages
*/
next = list_first_entry(list, struct page, lru);
/* exit on error */ if (err) break;
}
/* Rotate any leftover pages to the head of the freelist */ if (!list_entry_is_head(next, list, lru) && !list_is_first(&next->lru, list))
list_rotate_to_front(&next->lru, list);
/* Generate minimum watermark to be able to guarantee progress */
watermark = low_wmark_pages(zone) +
(PAGE_REPORTING_CAPACITY << page_reporting_order);
/* Process each free list starting from lowest order/mt */ for (order = page_reporting_order; order < NR_PAGE_ORDERS; order++) { for (mt = 0; mt < MIGRATE_TYPES; mt++) { /* We do not pull pages from the isolate free list */ if (is_migrate_isolate(mt)) continue;
/* report the leftover pages before going idle */
leftover = PAGE_REPORTING_CAPACITY - offset; if (leftover) {
sgl = &sgl[offset];
err = prdev->report(prdev, sgl, leftover);
/* flush any remaining pages out from the last report */
spin_lock_irq(&zone->lock);
page_reporting_drain(prdev, sgl, leftover, !err);
spin_unlock_irq(&zone->lock);
}
/* allocate scatterlist to store pages being reported on */
sgl = kmalloc_array(PAGE_REPORTING_CAPACITY, sizeof(*sgl), GFP_KERNEL); if (!sgl) goto err_out;
int page_reporting_register(struct page_reporting_dev_info *prdev)
{ int err = 0;
mutex_lock(&page_reporting_mutex);
/* nothing to do if already in use */ if (rcu_dereference_protected(pr_dev_info,
lockdep_is_held(&page_reporting_mutex))) {
err = -EBUSY; goto err_out;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.