@@ -346,27 +346,41 @@ static void batch_destroy(struct pfn_batch *batch, void *backup)
346
346
kfree (batch -> pfns );
347
347
}
348
348
349
- /* true if the pfn was added, false otherwise */
350
- static bool batch_add_pfn ( struct pfn_batch * batch , unsigned long pfn )
349
+ static bool batch_add_pfn_num ( struct pfn_batch * batch , unsigned long pfn ,
350
+ u32 nr )
351
351
{
352
352
const unsigned int MAX_NPFNS = type_max (typeof (* batch -> npfns ));
353
-
354
- if (batch -> end &&
355
- pfn == batch -> pfns [batch -> end - 1 ] + batch -> npfns [batch -> end - 1 ] &&
356
- batch -> npfns [batch -> end - 1 ] != MAX_NPFNS ) {
357
- batch -> npfns [batch -> end - 1 ]++ ;
358
- batch -> total_pfns ++ ;
359
- return true;
360
- }
361
- if (batch -> end == batch -> array_size )
353
+ unsigned int end = batch -> end ;
354
+
355
+ if (end && pfn == batch -> pfns [end - 1 ] + batch -> npfns [end - 1 ] &&
356
+ nr <= MAX_NPFNS - batch -> npfns [end - 1 ]) {
357
+ batch -> npfns [end - 1 ] += nr ;
358
+ } else if (end < batch -> array_size ) {
359
+ batch -> pfns [end ] = pfn ;
360
+ batch -> npfns [end ] = nr ;
361
+ batch -> end ++ ;
362
+ } else {
362
363
return false;
363
- batch -> total_pfns ++ ;
364
- batch -> pfns [batch -> end ] = pfn ;
365
- batch -> npfns [batch -> end ] = 1 ;
366
- batch -> end ++ ;
364
+ }
365
+
366
+ batch -> total_pfns += nr ;
367
367
return true;
368
368
}
369
369
370
+ static void batch_remove_pfn_num (struct pfn_batch * batch , unsigned long nr )
371
+ {
372
+ batch -> npfns [batch -> end - 1 ] -= nr ;
373
+ if (batch -> npfns [batch -> end - 1 ] == 0 )
374
+ batch -> end -- ;
375
+ batch -> total_pfns -= nr ;
376
+ }
377
+
378
+ /* true if the pfn was added, false otherwise */
379
+ static bool batch_add_pfn (struct pfn_batch * batch , unsigned long pfn )
380
+ {
381
+ return batch_add_pfn_num (batch , pfn , 1 );
382
+ }
383
+
370
384
/*
371
385
* Fill the batch with pfns from the domain. When the batch is full, or it
372
386
* reaches last_index, the function will return. The caller should use
@@ -622,6 +636,41 @@ static void batch_from_pages(struct pfn_batch *batch, struct page **pages,
622
636
break ;
623
637
}
624
638
639
+ static int batch_from_folios (struct pfn_batch * batch , struct folio * * * folios_p ,
640
+ unsigned long * offset_p , unsigned long npages )
641
+ {
642
+ int rc = 0 ;
643
+ struct folio * * folios = * folios_p ;
644
+ unsigned long offset = * offset_p ;
645
+
646
+ while (npages ) {
647
+ struct folio * folio = * folios ;
648
+ unsigned long nr = folio_nr_pages (folio ) - offset ;
649
+ unsigned long pfn = page_to_pfn (folio_page (folio , offset ));
650
+
651
+ nr = min (nr , npages );
652
+ npages -= nr ;
653
+
654
+ if (!batch_add_pfn_num (batch , pfn , nr ))
655
+ break ;
656
+ if (nr > 1 ) {
657
+ rc = folio_add_pins (folio , nr - 1 );
658
+ if (rc ) {
659
+ batch_remove_pfn_num (batch , nr );
660
+ goto out ;
661
+ }
662
+ }
663
+
664
+ folios ++ ;
665
+ offset = 0 ;
666
+ }
667
+
668
+ out :
669
+ * folios_p = folios ;
670
+ * offset_p = offset ;
671
+ return rc ;
672
+ }
673
+
625
674
static void batch_unpin (struct pfn_batch * batch , struct iopt_pages * pages ,
626
675
unsigned int first_page_off , size_t npages )
627
676
{
0 commit comments