| /* 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); | 
 | } |