]> Pileus Git - ~andy/linux/blobdiff - lib/scatterlist.c
lib/scatterlist: add simple page iterator
[~andy/linux] / lib / scatterlist.c
index 7874b01e816e815466ccee3a08387b075503c72f..a1d15647d7dbf29944b1de36cd8c8049893aaa8a 100644 (file)
@@ -394,6 +394,44 @@ int sg_alloc_table_from_pages(struct sg_table *sgt,
 }
 EXPORT_SYMBOL(sg_alloc_table_from_pages);
 
+void __sg_page_iter_start(struct sg_page_iter *piter,
+                         struct scatterlist *sglist, unsigned int nents,
+                         unsigned long pgoffset)
+{
+       piter->__pg_advance = 0;
+       piter->__nents = nents;
+
+       piter->page = NULL;
+       piter->sg = sglist;
+       piter->sg_pgoffset = pgoffset;
+}
+EXPORT_SYMBOL(__sg_page_iter_start);
+
+static int sg_page_count(struct scatterlist *sg)
+{
+       return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT;
+}
+
+bool __sg_page_iter_next(struct sg_page_iter *piter)
+{
+       if (!piter->__nents || !piter->sg)
+               return false;
+
+       piter->sg_pgoffset += piter->__pg_advance;
+       piter->__pg_advance = 1;
+
+       while (piter->sg_pgoffset >= sg_page_count(piter->sg)) {
+               piter->sg_pgoffset -= sg_page_count(piter->sg);
+               piter->sg = sg_next(piter->sg);
+               if (!--piter->__nents || !piter->sg)
+                       return false;
+       }
+       piter->page = nth_page(sg_page(piter->sg), piter->sg_pgoffset);
+
+       return true;
+}
+EXPORT_SYMBOL(__sg_page_iter_next);
+
 /**
  * sg_miter_start - start mapping iteration over a sg list
  * @miter: sg mapping iter to be started