|
@@ -512,7 +512,7 @@ struct scatterlist *sgl_alloc_order(unsigned long long length,
|
|
|
if (!sgl)
|
|
|
return NULL;
|
|
|
|
|
|
- sg_init_table(sgl, nent);
|
|
|
+ sg_init_table(sgl, nalloc);
|
|
|
sg = sgl;
|
|
|
while (length) {
|
|
|
elem_len = min_t(u64, length, PAGE_SIZE << order);
|
|
@@ -526,7 +526,7 @@ struct scatterlist *sgl_alloc_order(unsigned long long length,
|
|
|
length -= elem_len;
|
|
|
sg = sg_next(sg);
|
|
|
}
|
|
|
- WARN_ON_ONCE(sg);
|
|
|
+ WARN_ONCE(length, "length = %lld\n", length);
|
|
|
if (nent_p)
|
|
|
*nent_p = nent;
|
|
|
return sgl;
|
|
@@ -549,22 +549,44 @@ struct scatterlist *sgl_alloc(unsigned long long length, gfp_t gfp,
|
|
|
EXPORT_SYMBOL(sgl_alloc);
|
|
|
|
|
|
/**
|
|
|
- * sgl_free_order - free a scatterlist and its pages
|
|
|
+ * sgl_free_n_order - free a scatterlist and its pages
|
|
|
* @sgl: Scatterlist with one or more elements
|
|
|
+ * @nents: Maximum number of elements to free
|
|
|
* @order: Second argument for __free_pages()
|
|
|
+ *
|
|
|
+ * Notes:
|
|
|
+ * - If several scatterlists have been chained and each chain element is
|
|
|
+ * freed separately then it's essential to set nents correctly to avoid that a
|
|
|
+ * page would get freed twice.
|
|
|
+ * - All pages in a chained scatterlist can be freed at once by setting @nents
|
|
|
+ * to a high number.
|
|
|
*/
|
|
|
-void sgl_free_order(struct scatterlist *sgl, int order)
|
|
|
+void sgl_free_n_order(struct scatterlist *sgl, int nents, int order)
|
|
|
{
|
|
|
struct scatterlist *sg;
|
|
|
struct page *page;
|
|
|
+ int i;
|
|
|
|
|
|
- for (sg = sgl; sg; sg = sg_next(sg)) {
|
|
|
+ for_each_sg(sgl, sg, nents, i) {
|
|
|
+ if (!sg)
|
|
|
+ break;
|
|
|
page = sg_page(sg);
|
|
|
if (page)
|
|
|
__free_pages(page, order);
|
|
|
}
|
|
|
kfree(sgl);
|
|
|
}
|
|
|
+EXPORT_SYMBOL(sgl_free_n_order);
|
|
|
+
|
|
|
+/**
|
|
|
+ * sgl_free_order - free a scatterlist and its pages
|
|
|
+ * @sgl: Scatterlist with one or more elements
|
|
|
+ * @order: Second argument for __free_pages()
|
|
|
+ */
|
|
|
+void sgl_free_order(struct scatterlist *sgl, int order)
|
|
|
+{
|
|
|
+ sgl_free_n_order(sgl, INT_MAX, order);
|
|
|
+}
|
|
|
EXPORT_SYMBOL(sgl_free_order);
|
|
|
|
|
|
/**
|