iommufd: Folio subroutines

Add subroutines for copying folios to a batch.

Link: https://patch.msgid.link/r/1729861919-234514-6-git-send-email-steven.sistare@oracle.com
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Steve Sistare
2024-10-25 06:11:55 -07:00
committed by Jason Gunthorpe
parent c27f0a606c
commit ed9178fbfd

View File

@@ -346,25 +346,39 @@ static void batch_destroy(struct pfn_batch *batch, void *backup)
kfree(batch->pfns);
}
static bool batch_add_pfn_num(struct pfn_batch *batch, unsigned long pfn,
u32 nr)
{
const unsigned int MAX_NPFNS = type_max(typeof(*batch->npfns));
unsigned int end = batch->end;
if (end && pfn == batch->pfns[end - 1] + batch->npfns[end - 1] &&
nr <= MAX_NPFNS - batch->npfns[end - 1]) {
batch->npfns[end - 1] += nr;
} else if (end < batch->array_size) {
batch->pfns[end] = pfn;
batch->npfns[end] = nr;
batch->end++;
} else {
return false;
}
batch->total_pfns += nr;
return true;
}
static void batch_remove_pfn_num(struct pfn_batch *batch, unsigned long nr)
{
batch->npfns[batch->end - 1] -= nr;
if (batch->npfns[batch->end - 1] == 0)
batch->end--;
batch->total_pfns -= nr;
}
/* true if the pfn was added, false otherwise */
static bool batch_add_pfn(struct pfn_batch *batch, unsigned long pfn)
{
const unsigned int MAX_NPFNS = type_max(typeof(*batch->npfns));
if (batch->end &&
pfn == batch->pfns[batch->end - 1] + batch->npfns[batch->end - 1] &&
batch->npfns[batch->end - 1] != MAX_NPFNS) {
batch->npfns[batch->end - 1]++;
batch->total_pfns++;
return true;
}
if (batch->end == batch->array_size)
return false;
batch->total_pfns++;
batch->pfns[batch->end] = pfn;
batch->npfns[batch->end] = 1;
batch->end++;
return true;
return batch_add_pfn_num(batch, pfn, 1);
}
/*
@@ -622,6 +636,41 @@ static void batch_from_pages(struct pfn_batch *batch, struct page **pages,
break;
}
static int batch_from_folios(struct pfn_batch *batch, struct folio ***folios_p,
unsigned long *offset_p, unsigned long npages)
{
int rc = 0;
struct folio **folios = *folios_p;
unsigned long offset = *offset_p;
while (npages) {
struct folio *folio = *folios;
unsigned long nr = folio_nr_pages(folio) - offset;
unsigned long pfn = page_to_pfn(folio_page(folio, offset));
nr = min(nr, npages);
npages -= nr;
if (!batch_add_pfn_num(batch, pfn, nr))
break;
if (nr > 1) {
rc = folio_add_pins(folio, nr - 1);
if (rc) {
batch_remove_pfn_num(batch, nr);
goto out;
}
}
folios++;
offset = 0;
}
out:
*folios_p = folios;
*offset_p = offset;
return rc;
}
static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages,
unsigned int first_page_off, size_t npages)
{