|  | /* Copyright (c) 2016 Google Inc. | 
|  | * Barret Rhoden <brho@cs.berkeley.edu> | 
|  | * See LICENSE for details. | 
|  | * | 
|  | * Helpers for reference counted pages, for use with Linux code. | 
|  | * | 
|  | * Some code wants to use reference counted pages.  I'd like to keep these | 
|  | * uses separate from the main memory allocator.  Code that wants reference | 
|  | * counted pages can use these helpers. | 
|  | * | 
|  | * Pass in memory allocated with get_cont_pages(). */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <kref.h> | 
|  | #include <page_alloc.h> | 
|  | #include <pmap.h> | 
|  | #include <kmalloc.h> | 
|  | #include <assert.h> | 
|  |  | 
|  | struct refd_pages { | 
|  | void				*rp_kva; | 
|  | size_t				rp_order; | 
|  | struct kref			rp_kref; | 
|  | }; | 
|  |  | 
|  | static struct page *rp2page(struct refd_pages *rp) | 
|  | { | 
|  | return kva2page(rp->rp_kva); | 
|  | } | 
|  |  | 
|  | static void refd_pages_release(struct kref *kref) | 
|  | { | 
|  | struct refd_pages *rp = container_of(kref, struct refd_pages, rp_kref); | 
|  |  | 
|  | free_cont_pages(rp->rp_kva, rp->rp_order); | 
|  | kfree(rp); | 
|  | } | 
|  |  | 
|  | static struct refd_pages *get_refd_pages(void *kva, size_t order) | 
|  | { | 
|  | struct refd_pages *rp; | 
|  |  | 
|  | if (!kva) | 
|  | return 0; | 
|  | rp = kmalloc(sizeof(struct refd_pages), MEM_WAIT); | 
|  | assert(rp); | 
|  | rp->rp_kva = kva; | 
|  | rp->rp_order = order; | 
|  | kref_init(&rp->rp_kref, refd_pages_release, 1); | 
|  | return rp; | 
|  | } | 
|  |  | 
|  | static void refd_pages_decref(struct refd_pages *rp) | 
|  | { | 
|  | kref_put(&rp->rp_kref); | 
|  | } |